import gtk
from threading import Thread
from os import listdir
from time import sleep, time

#TODO: implement undo functionality for plots

class Plot(gtk.EventBox):
    '''
    This widget capsulates a sympy.Plot-object and so enables
    plotting functionality.
    '''
    
    def __init__(self, DOM, settings, parsers):
        gtk.EventBox.__init__(self)
        self.show()
        
        self.settings = settings
        self.parsers = parsers
        
        self.connect('button_press_event', self._event_openInteractiv)
        self.connect('enter-notify-event', self._event_mouseEnter)
        self.connect('leave-notify-event', self._event_mouseLeave)
        
        self.DOM = DOM
        self.changed = False
        self.plot = None #here iss the sympy.Plot object stored
        
        #this is a path into the 'temp_pictures' directory
        self.createUniquePath()
        
        #create the gtk.Image where tho screenshots of the
        #plotting window is shown.
        self.image = gtk.Image()
        self.image.show()
        self.add(self.image)
        
        #produce a first screenshot without opening the
        #inteactive window.
        self.Thread = Thread(target=self.screenshot)
        self.Thread.start()
        
    def _event_mouseEnter(self, widget, event):
        '''
        Changes the curser to a plus when it enters.
        '''
        
        cursor = gtk.gdk.PLUS
        gtk.gdk.Window.set_cursor(self.window, gtk.gdk.Cursor(gtk.gdk.EXCHANGE))
        
    def _event_mouseLeave(self, widget, event):
        '''
        Changes the cursor back to normal when it leaves.
        '''
        
        cursor = gtk.gdk.ARROW
        gtk.gdk.Window.set_cursor(self.window, gtk.gdk.Cursor(gtk.gdk.ARROW))
        
    def _event_openInteractiv(self, widget, event):
        '''
        Opens the intaractive plotting window when the widget is doubleclicked.
        '''
        
        if event.type!=gtk.gdk._2BUTTON_PRESS:
            return
        
        self.changed = True
        
        if not self.path:
            self.createUniquePath()
        
        #create a new plot-object if necessary and start session    
        if not self.plot or self.plot._window.has_exit:
            self.plot = self.parsers['plot'].dom_to_plot(self.DOM)
            Thread(target=self._updateLoop).start()
        else:
            self.plot._window.set_visible(True)
            
    def _updateLoop(self):
        '''
        Updates the widget in a certain interval, as long as the
        interactive window is opened. Afterwards it gets the new
        DOM reapresentation of the plot-object.
        '''
        
        interval = 1
        last = 0
        while not self.plot._window.has_exit:
            t = time()
            if t-last>interval:
                last = t
                self.plot.saveimage(self.path)
                self.showImage()
            sleep(0.5)
        self.showImage()
        self.DOM = self.parsers['plot'].plot_to_dom(self.plot)   
    
    def screenshot(self):
        '''
        Creates a screenshot without opening the interactive window.
        '''
        
        #create a new plot object if necessary
        if not self.plot or self.plot._window.has_exit:
            self.plot = self.parsers['plot'].dom_to_plot(self.DOM, interactive=False)
            
        self.plot.saveimage(self.path)
        
        #now wait until image is saved
        self.plot._window.Thread.join()
        self.showImage()
    
    def showImage(self):
        '''
        Loads the image from self.path and diplays it.
        '''
        
        self.image.set_from_file(self.path)
            
    def createUniquePath(self):
        '''
        Searches a not used filename in the 'temp_pictures' directory 
        and creates an empty file. Saves the path into self.path.
        '''
        
        l = listdir(self.settings.dirs['temp_pictures'])
        i=0
        while True:
            if not 'pic%s.png'%i in l:
                self.path = self.settings.dirs['temp_pictures']+'pic%s.png'%i
                break
            i+=1
        f = open(self.path, 'w')
        f.close()
            
    def todom(self):
        '''
        Returns a DOM representation of the plot-object.
        '''
        
        self.DOM.setAttribute('path',self.path)
        return self.DOM
    
    def toxml(self):
        '''
        Returns a xml representation of the plot-object.
        '''
        
        return self.getDOM().toxml()
    
    def destroy(self):
        '''
        Cleans up everything.
        '''
        
        gtk.EventBox.destroy(self)
        self.image.destroy()
        if self.plot and not self.plot._window.has_exit:
            self.plot.close()